from utils.common_import import *
from .model import PAI_PROJECT, PAI_PROJECT_JOB, IntervalQuerySchema
from utils.ext import inner_db
from app.containers.containers import get_jobs_status
from .dashboard import top_number_users_resource, get_time_day_edge_millsecond, make_zero_time_series,\
            HOUR_UNIT_TIME_MILL_SECOND, DAY_UNIT_TIME_MILL_SECOND, MILL_SECOND, TOP_NUM


#用户任务数目Top
class TopUsersJobsNumberView(Resource):
    # @jwt_required()
    @exception_response()
    def get(self):
        #返回 ('项目名称', '项目id','任务个数')
        project_jobs = inner_db.session.query(PAI_PROJECT_JOB.project_name, PAI_PROJECT_JOB.project_id,
                                              inner_db.func.count('*').label('job_number'))\
            .group_by(PAI_PROJECT_JOB.project_id).all()

        # logger.info("project_jobs is {}".format(project_jobs))

        #处理任务为空情形
        if not project_jobs:
            logger.info("there is no project_jobs ")
            return  make_success_response([])

        #统计用户任务数目
        user_jobs_map = self._count_user_jobs(project_jobs)

        #获取top num用户
        top_user_account_list = top_number_users_resource(inner_db.session, TOP_NUM, user_jobs_map)

        return make_success_response(top_user_account_list)

    def _get_user_project_map(self):
        #查询所有项目
        projects = inner_db.session.query(PAI_PROJECT.project_name, PAI_PROJECT.id, PAI_PROJECT.user_id).all()

        #构建项目与用户对应关系
        projects_map = {}
        for project in projects:
            project_id = str(project[1])
            user_id = project[2]
            projects_map[project_id] = user_id

        return projects_map

    def _count_user_jobs(self, project_jobs):
        projects_map = self._get_user_project_map()
        #统计用户任务数目
        user_jobs_map = {}
        for project_job in project_jobs:
            project_id = str(project_job[1])
            if not project_id in projects_map:
                #处理项目没有找到用户异常
                logger.warning("project name {} not find user".format(project_id))
                continue

            user_id = projects_map[project_id]
            job_nums = project_job[2]
            user_jobs_map.setdefault(user_id, 0)
            user_jobs_map[user_id] += job_nums

        return user_jobs_map

#用户任务总时长Top
class TopUsersJobsHourView(Resource):
    # @jwt_required()
    @request_arg_check(IntervalQuerySchema(), location="args")
    @exception_response()
    def get(self):
        interval = current_schema_instance["query_interval"]
        time_range = get_time_day_edge_millsecond(interval)
        #以0点作为统计点
        begin_time = time_range["start_day"]

        jobs_name_list = inner_db.session.query(PAI_PROJECT_JOB.job_name).\
            filter(PAI_PROJECT_JOB.create_time > begin_time).all()

        #处理任务为空情形
        if not jobs_name_list:
            logger.info("there is no record is {} days".format(interval))
            return  make_success_response([])

        #用户任务总时间
        user_jobs_hours=self._get_user_jobs_hours(jobs_name_list)

        #top num 用户
        top_user_jobs_hours = top_number_users_resource(inner_db.session, TOP_NUM, user_jobs_hours)

        return  make_success_response(top_user_jobs_hours)

    def _get_user_jobs_hours(self, records):
        jobs_name_list = [job_tuple[0] for job_tuple in records]
        logger.debug(jobs_name_list)

        jobs_status = get_jobs_status(jobs_name_list)
        logger.debug(jobs_status)

        user_jobs_hours = {}
        for job in jobs_status:
            user_name = job.user()
            user_jobs_hours.setdefault(user_name, 0)
            # job_start_time = job['firstRequestTimestamp']
            #
            # if job['frameworkCompletedTimestamp']:
            #     job_end_time = job['frameworkCompletedTimestamp']
            # else:
            #     job_end_time = time.time()*MILL_SECOND

            duration = job.duration()/HOUR_UNIT_TIME_MILL_SECOND
            duration = float("{:.2f}".format(duration))

            user_jobs_hours[user_name] += duration

        return user_jobs_hours

#获取一段时间内活跃用户数
#当前做简化处理 只统计提交任务的用户数
class UsersView(Resource):
    # @jwt_required()
    @request_arg_check(IntervalQuerySchema(), location="args")
    @exception_response()
    def get(self):
        interval = current_schema_instance["query_interval"]
        time_range = get_time_day_edge_millsecond(interval)
        #以0点作为统计点
        begin_day_time = time_range["start_day"]

        #获取任务按照时间升序
        records = inner_db.session.query(PAI_PROJECT_JOB.job_name, PAI_PROJECT_JOB.create_time).\
                    filter(PAI_PROJECT_JOB.create_time >= begin_day_time).\
                    order_by(PAI_PROJECT_JOB.create_time).all()

        #处理任务为空情形
        if not records:
            result_empty = make_zero_time_series(begin_day_time, interval)
            return  make_success_response(result_empty)

        jobs_time_list = self._get_users_time_map( begin_day_time, records)

        return make_success_response(jobs_time_list)

    def _get_users_time_map(self, begin_day_time, records):
        #任务名称和用户对应管辖
        jobs_name_list = [record[0] for record in records]
        logger.info(jobs_name_list)
        jobs_status_list = get_jobs_status(jobs_name_list)

        #构建用户与任务对应关系
        jobs_users_map = {}
        for job_info in jobs_status_list:
            jobs_users_map[job_info.name()] = job_info.user()

        users_time_map = {}
        start = begin_day_time
        for record in records:
            job_name = record[0]
            if not job_name in jobs_users_map:
                logger.warning("{} not find user".format(job_name))
                continue

            user_id = jobs_users_map[job_name]
            job_create_time = record[1]

            #获取的任务本身是升序的，这里只要找到边界就好
            while start < job_create_time:
                start += DAY_UNIT_TIME_MILL_SECOND

            # start 已经移动到任务时间的右侧， 获取左侧时间作为统计时间
            target = start - DAY_UNIT_TIME_MILL_SECOND
            users_time_map.setdefault(str(target), [])
            #统计没有添加的用户
            if user_id not in users_time_map[str(target)]:
                users_time_map[str(target)].append(user_id)
        # logger.info("users_add_list is {}".format(users_time_map))

        jobs_time_list = []
        for time_stamp in users_time_map:
            jobs_time_list.append([int(time_stamp), len(users_time_map[time_stamp])])

        return jobs_time_list
